﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder.Modelling.Components.Actions
{
    public class ActionAlignSelectedShprosses : IComponentAction
    {
        private ModelControl modelControl;
        private bool moveConnectedComponents;
        private ComponentAlign align;

        public ActionAlignSelectedShprosses(ModelControl modelControl, ComponentAlign align, bool moveConnectedComponents)
        {
            this.modelControl = modelControl;
            this.align = align;
            this.moveConnectedComponents = moveConnectedComponents;
        }

        #region IComponentAction Members

        public bool Action(IComponent component)
        {
            List<IComponent> componentsToAlign = new List<IComponent>();
            if (!(component is Shpross))
                return false;

            foreach(IComponent selectedComponent in modelControl.ModelContainer.SelectedComponentsStack)
                if (selectedComponent is Shpross && component != selectedComponent)
                    componentsToAlign.Add(selectedComponent);

            switch (align)
            {
                case ComponentAlign.Horizontal:
                    return this.HorizontalAlign(componentsToAlign, component);
                case ComponentAlign.Vertical:
                    return this.VerticalAlign(componentsToAlign, component);
                default:
                    throw new NotImplementedException();
            }
            return false;            
        }

        #endregion

        private bool HorizontalAlign(List<IComponent> componentsToAlign, IComponent component)
        {
            Shpross shpross = component as Shpross;

            ModelPoint pointToAlign = shpross.GetSelectedPoint();
            foreach (IComponent componentToAlign in componentsToAlign)
            {
                Shpross shprossToAlign = componentToAlign as Shpross;
                if (shprossToAlign.SelectedPoint == ShprossPoints.Center)
                    continue;
                ModelPoint moveToPoint;
                switch (shprossToAlign.SelectedPoint)
                {
                    case ShprossPoints.Start:
                        moveToPoint = new ModelPoint(shprossToAlign.StartPoint.X, pointToAlign.Y);

                        if (moveConnectedComponents)
                        {
                            ModelVector vector = new ModelVector(shprossToAlign.StartConnectedComponent.Position, moveToPoint);
                            if (shprossToAlign.StartConnectedComponent.GetType() == typeof(Connector))
                                shprossToAlign.StartConnectedComponent.Parent.MoveWithOffset(vector);
                        }
                        else
                            shprossToAlign.RemoveInnerComponent(shprossToAlign.StartConnectedComponent);
                        shprossToAlign.MoveStartPointTo(moveToPoint);
                        break;
                    case ShprossPoints.End:
                        moveToPoint = new ModelPoint(shprossToAlign.EndPoint.X, pointToAlign.Y);

                        if (moveConnectedComponents)
                        {
                            ModelVector vector = new ModelVector(shprossToAlign.EndConnectedComponent.Position, moveToPoint);
                            if (shprossToAlign.EndConnectedComponent.GetType() == typeof(Connector))
                                shprossToAlign.EndConnectedComponent.Parent.MoveWithOffset(vector);
                        }
                        else
                            shprossToAlign.RemoveInnerComponent(shprossToAlign.EndConnectedComponent);

                        shprossToAlign.MoveEndPointTo(moveToPoint);
                        break;
                }
            }
            return true;
        }
        

        private bool VerticalAlign(List<IComponent> componentsToAlign, IComponent component)
        {
            Shpross shpross = component as Shpross;
         
            ModelPoint pointToAlign = shpross.GetSelectedPoint();
            foreach (IComponent componentToAlign in componentsToAlign)
            {
                Shpross shprossToAlign = componentToAlign as Shpross;
                if (shprossToAlign.SelectedPoint == ShprossPoints.Center)
                    continue;

                ModelPoint moveToPoint;
                switch (shprossToAlign.SelectedPoint)
                {
                    case ShprossPoints.Start:
                        moveToPoint = new ModelPoint(pointToAlign.X, shprossToAlign.StartPoint.Y);
                        if (moveConnectedComponents)
                        {
                            ModelVector vector = new ModelVector(shprossToAlign.StartConnectedComponent.Position, moveToPoint);
                            if (shprossToAlign.StartConnectedComponent.GetType() == typeof(Connector))
                                shprossToAlign.StartConnectedComponent.Parent.MoveWithOffset(vector, shprossToAlign.Parent.BoundingBox);
                        }
                        else
                            shprossToAlign.RemoveInnerComponent(shprossToAlign.StartConnectedComponent);
                        shprossToAlign.MoveStartPointTo(moveToPoint, shprossToAlign.Parent.BoundingBox, false);
                        break;

                    case ShprossPoints.End:
                        moveToPoint = new ModelPoint(pointToAlign.X, shprossToAlign.EndPoint.Y);
                        if (moveConnectedComponents)
                        {
                            ModelVector vector = new ModelVector(shprossToAlign.EndConnectedComponent.Position, moveToPoint);
                            if (shprossToAlign.EndConnectedComponent.GetType() == typeof(Connector))
                                shprossToAlign.EndConnectedComponent.Parent.MoveWithOffset(vector, shprossToAlign.Parent.BoundingBox);

                        }
                        else
                            shprossToAlign.RemoveInnerComponent(shprossToAlign.EndConnectedComponent);

                        shprossToAlign.MoveEndPointTo(moveToPoint, shprossToAlign.Parent.BoundingBox, false);
                        break;
                }
            }
            return true;

        }

    }

}
